package com.wxj.bank.module.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wxj.bank.module.constant.Constants;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author shengtao
 * @Description: http工具
 * @date 2019/01/30 10:52
 */
public class HttpUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);

    private static final PoolingHttpClientConnectionManager HTTP_CLIENT_CONNECTION_MANAGER;
    private static final CloseableHttpClient HTTP_CLIENT;

    static {
        HTTP_CLIENT_CONNECTION_MANAGER = new PoolingHttpClientConnectionManager(
                RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory()).build());
        HTTP_CLIENT_CONNECTION_MANAGER.setDefaultMaxPerRoute(100);
        HTTP_CLIENT_CONNECTION_MANAGER.setMaxTotal(200);
        RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(60000).setConnectTimeout(60000).setSocketTimeout(60000).build();
        HTTP_CLIENT = HttpClientBuilder.create().setConnectionManager(HTTP_CLIENT_CONNECTION_MANAGER).setDefaultRequestConfig(requestConfig).build();
    }

    /**
     * post请求
     * @param url
     * @param json
     * @param header
     * @return
     */
    public static String post(String url,String json,String header){
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            //创建 http 请求
            HttpPost post = new HttpPost(url);
            //加载请求参数
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            entity.setContentEncoding(Constants.CHARACTER_DEFAULT);
            post.setEntity(entity);
            //加载请求头 header
            if(StringUtils.isNotBlank(header)){
                post.setHeaders(conventHeaders(header));
            }
            // 执行http请求
            response = HTTP_CLIENT.execute(post);
            consumeResponse(response, Constants.CHARACTER_DEFAULT);
        } catch (Exception e) {
            LOGGER.error("url:{} post请求异常", url, e);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                LOGGER.error("关闭响应异常", e);
            }
        }
        return resultString;
    }

    /**
     * 处理返回的请求,拿到返回内容
     * @param response 要处理的返回
     * @return 返回的内容
     */
    private static String consumeResponse(CloseableHttpResponse response, String characterDefault) {
        String resultString = null;
        try {
            HttpEntity httpResponse = response.getEntity();
            if(httpResponse != null){
                resultString = EntityUtils.toString(httpResponse,characterDefault);
                EntityUtils.consume(httpResponse);
            }
        } catch (IOException e) {
            LOGGER.error("response 解析异常",e);
        }finally {
            try {
                response.close();
            } catch (IOException e) {
                LOGGER.error("关闭响应异常", e);
            }
        }
        return resultString;
    }

    /**
     * 创建消息头
     * @param header
     * @return
     */
    private static Header[] conventHeaders(String header) {
        JSONObject jsonObject = JSON.parseObject(header);
        if(jsonObject == null){
            return null;
        }
        List<Header> headers = new ArrayList<>();
        for (String key:jsonObject.keySet()){
            headers.add(new BasicHeader(key,jsonObject.getString(key)));
        }
        return headers.toArray(new Header[]{});
    }

    /**
     * 构造HttpGet请求
     * @param url
     * @param json
     * @param header
     * @return
     */
    public static String get(String url,String json,String header){
        CloseableHttpResponse httpResponse = null;
        String resultString = null;
        try {
            //构造参数
            if(StringUtils.isNotBlank(json)){
                url = conventUrl(url,json);
            }
            //构建HttpGet对象
            HttpGet get = new HttpGet(url);
            //设置header
            get.setHeaders(conventHeaders(header));
            httpResponse = HTTP_CLIENT.execute(get);
            resultString = consumeResponse(httpResponse,Constants.CHARACTER_DEFAULT);
        } catch (Exception e) {
            LOGGER.error("url:{} get请求异常", url, e);
        }finally {
            try {
                if (httpResponse != null) {
                    httpResponse.close();
                }
            } catch (IOException e) {
                LOGGER.error("关闭响应异常", e);
            }
        }
        return resultString;
    }

    /**
     * 构造url参数
     * @param url
     * @param json
     * @return
     */
    private static String conventUrl(String url, String json) {
        StringBuilder param = new StringBuilder();
        if(url.contains(Constants.SYMBOL_ASK)){
            param.append(url.split(Constants.SYMBOL_ASK)[1]).append(Constants.SYMBOL_AND);
        }
        JSONObject jsonObject = JSONObject.parseObject(json);
        if(jsonObject == null){
            return url;
        }
        for (String key:jsonObject.keySet()){
            param.append(key).append(Constants.SYMBOL_EQUAL).append(jsonObject.getString(key)).append(Constants.SYMBOL_AND);
        }
        return param.toString().substring(0,param.toString().length() - 1);
    }

}
